/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import {BreakpointInfo} from '../breakpoint/BreakpointInfo'
import {BlockInfo} from '../breakpoint/BlockInfo'
import {DownloadTask} from '../DownloadTask'
import {ResumeFailedCause} from '../cause/ResumeFailedCause'

export class BreakpointLocalCheck {
    private dirty: boolean;
    fileExist: boolean;
    infoRight: boolean;
    outputStreamSupport: boolean;

    private task: DownloadTask;
    private info: BreakpointInfo;
    private responseInstanceLength: number;

    /**
     * @param responseInstanceLength if the value is larger than {@code 0}, this value will used to
     *                               compare with the old instance-length save on the {@code info}.
     */
    public constructor(task: DownloadTask, info: BreakpointInfo, responseInstanceLength: number) {
        this.task = task;
        this.info = info;
        this.responseInstanceLength = responseInstanceLength;
    }

    /**
     * Get whether the local data is dirty. only if one of the {@code fileExist} or
     * {@code infoRight} or {@code outputStreamSupport} is {@code false}, the result will be
     * {@code false}.
     *
     * @return whether the local data is dirty.
     */
    public isDirty(): boolean {
        return this.dirty;
    }

    /**
     * Get cause and if the cause isn't exist  throw the {@link IllegalStateException}.
     *
     * @return the cause of resume failed.
     */
   public getCauseOrThrow(): ResumeFailedCause {
        if (!this.infoRight) {
            return ResumeFailedCause.INFO_DIRTY;
        } else if (!this.fileExist) {
            return ResumeFailedCause.FILE_NOT_EXIST;
        } else if (!this.outputStreamSupport) {
            return ResumeFailedCause.OUTPUT_STREAM_NOT_SUPPORT;
        }

        throw new Error("No cause find with dirty: " + this.dirty);
    }

    public isInfoRightToResume(): boolean {
        const blockCount: number = this.info.getBlockCount();

        if (blockCount <= 0) return false;
        if (this.info.isChunked()) return false;
        if (this.info.getFilename() == null) return false;
        const fileOnTask: string = this.task.getFilename();
        if (this.info.getFilename() !== fileOnTask) return false;
//        if (info.getFile().length() > info.getTotalLength()) return false;

        if (this.responseInstanceLength > 0 && this.info.getTotalLength() !== this.responseInstanceLength) {
            return false;
        }

        for (var i = 0; i < blockCount; i++) {
            let blockInfo: BlockInfo = this.info.getBlock(i);
            if (blockInfo.getContentLength() <= 0) return false;
        }

        return true;
    }

//    public boolean isOutputStreamSupportResume() {
//        final boolean supportSeek = OkDownload.with().outputStreamFactory().supportSeek();
//        if (supportSeek) return true;
//
//        if (info.getBlockCount() != 1) return false;
//        if (OkDownload.with().processFileStrategy().isPreAllocateLength(task)) return false;
//
//        return true;
//    }
//
//    public boolean isFileExistToResume() {
//        final Uri uri = task.getUri();
//        if (Util.isUriContentScheme(uri)) {
//            return Util.getSizeFromContentUri(uri) > 0;
//        } else {
//            final File file = task.getFile();
//            return file != null && file.exists();
//        }
//    }
//
//    public void check() {
//        fileExist = isFileExistToResume();
//        infoRight = isInfoRightToResume();
//        outputStreamSupport = isOutputStreamSupportResume();
//        dirty = !infoRight || !fileExist || !outputStreamSupport;
//    }
}